package com.xhwl.centiotdata.handler.pedestrian.impl;

import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.handler.pedestrian.PedestrianIntegrationFactory;
import com.xhwl.centiotdata.handler.pedestrian.PedestrianIntegrationHandler;
import com.xhwl.centiotdata.pojo.dto.haikang.PedestrianRecordHaiKangDTO;
import com.xhwl.centiotdata.pojo.dto.haikang.PersonInfoHaiKangDTO;
import com.xhwl.centiotdata.pojo.dto.haikang.RegionHaiKangDTO;
import com.xhwl.centiotdata.pojo.dto.pedestrian.PedestrianIntegrationConfigDTO;
import com.xhwl.centiotdata.service.cent.IAuthAccountCentService;
import com.xhwl.centiotdata.service.cent.IPedestrianCentService;
import com.xhwl.centiotdata.service.impl.DeviceServiceImpl;
import com.xhwl.centiotdata.service.sysconfig.ISsyConfigService;
import com.xhwl.centiotdata.suppliersystem.haikang.PedestrianHaiKangHandler;
import com.xhwl.centiotdata.suppliersystem.haikang.RegionHaiKangHandler;
import com.xhwl.centiotdata.suppliersystem.haikang.UserHaiKangHandler;
import com.xhwl.centiotdata.suppliersystem.haikang.VistorHaikangHandler;
import com.xhwl.common.dto.auth.PedestrianAuthDTO;
import com.xhwl.common.dto.cent.device.DeviceDTO;
import com.xhwl.common.dto.cent.pedes.AuthDTO;
import com.xhwl.common.dto.cent.pedes.OpenDoorRecordDTO;
import com.xhwl.common.enums.*;
import com.xhwl.common.enums.config.BusinessType;
import com.xhwl.common.enums.pedestrian.DoorActionEnum;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.ParameterConfig;
import com.xhwl.common.pojo.cent.auth.AuthAccountMapping;
import com.xhwl.common.pojo.criteria.ParamConfigCriteria;
import com.xhwl.common.utils.DateUtils;
import com.xhwl.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author： lianghz
 * @Description：
 * @Date 2021/11/03/ 13:48
 */
@Service
@Slf4j
public class PedestrianIntegrationHaiKangHandler extends PedestrianIntegrationHandler {

    @Autowired
    private PedestrianHaiKangHandler pedestrianHaiKangHandler;
    @Autowired
    private VistorHaikangHandler vistorHaikangHandler;
    @Autowired
    private UserHaiKangHandler userHaiKangHandler;
    @Autowired
    private RegionHaiKangHandler regionHaiKangHandler;
    @Autowired
    private IPedestrianCentService pedestrianCentService;
    @Autowired
    private DeviceServiceImpl deviceService;

    @Autowired
    private IAuthAccountCentService iAuthAccountCentService;
    @Autowired
    private ISsyConfigService iSsyConfigService;

    @Override
    public void afterPropertiesSet() throws Exception {
        PedestrianIntegrationFactory.register(2, this);
    }

    @Override
    public void pullRecord(PedestrianIntegrationConfigDTO configDTO, Integer intervalDays, Date date) {
        // 拉取数据
        List<PedestrianRecordHaiKangDTO> recordHaiKangDTOList = pedestrianHaiKangHandler.pullRecord(configDTO, date);
        if (CollectionUtils.isEmpty(recordHaiKangDTOList)) {
            return;
        }
        // 转换数据
        List<OpenDoorRecordDTO> openDoorRecordDTOList = this.handleRecord(configDTO, recordHaiKangDTOList);
        // 存储业务中台
        pedestrianCentService.saveBatch(openDoorRecordDTOList);
    }

    @Override
    public ResultJson createAuth(PedestrianIntegrationConfigDTO configDTO, PedestrianAuthDTO pedestrianAuthDTO) {
        log.info("海康权限新增:");
        log.info(JSONObject.toJSONString(pedestrianAuthDTO));
        List<DeviceDTO> deviceDTOS = deviceService.findDevice(pedestrianAuthDTO.getIndustryId(), null, CategoryEnum.DOOR.getId(), pedestrianAuthDTO.getDeviceIdList());
        // 授权
        AuthDTO authDTO = new AuthDTO();
        authDTO.setUserId(pedestrianAuthDTO.getSourceId());
        authDTO.setDeviceOpenIdList(deviceDTOS.stream().filter(t -> t.getProductId().equals(ProductEnum.HAIKANG_ISC.getId())).map(DeviceDTO::getThirdDeviceId).collect(Collectors.toList()));
        authDTO.setStartTime(pedestrianAuthDTO.getValidStartTime());
        authDTO.setEndTime(pedestrianAuthDTO.getValidEndTime());
        List<String> list = Optional.ofNullable(pedestrianAuthDTO.getCardNumberList()).orElse(new LinkedList<>());
        if (pedestrianAuthDTO.getCardNumber() != null) {
            list.add(pedestrianAuthDTO.getCardNumber());
        }
        List<String> userOpenIds = pedestrianAuthDTO.getUserOpenIds();
        if (Objects.nonNull(userOpenIds)) {
            authDTO.setUserOpenIdList(userOpenIds);
        } else {
            String userOpenId = pedestrianAuthDTO.getUserOpenId();
            if (StringUtils.isNotEmpty(userOpenId)) {
                authDTO.setUserOpenIdList(Collections.singletonList(userOpenId));
            } else {
                Integer accountId = pedestrianAuthDTO.getAccountId();
                if (Objects.nonNull(accountId)) {
                    AuthAccountMapping authA = iAuthAccountCentService.query(pedestrianAuthDTO.getProjectId(), accountId, pedestrianAuthDTO.getProductId());
                    if (Objects.nonNull(authA) && StringUtils.isNotEmpty(authA.getOpenId())) {
                        authDTO.setUserOpenIdList(Collections.singletonList(authA.getOpenId()));
                    }
                } else {
                    List<Integer> accountIds = pedestrianAuthDTO.getAccountIds();
                    if (Objects.nonNull(accountIds)) {
                        Set<String> openIds = new HashSet<>();
                        accountIds.forEach(t -> {
                            AuthAccountMapping authA = iAuthAccountCentService.query(pedestrianAuthDTO.getProjectId(), t, pedestrianAuthDTO.getProductId());
                            if (Objects.nonNull(authA) && StringUtils.isNotEmpty(authA.getOpenId())) {
                                openIds.add(authA.getOpenId());
                            }
                        });
                        authDTO.setUserOpenIdList(new ArrayList<>(openIds));
                    }
                }
            }
        }
        log.info("-------------------------------------开始授权操作-------------------------------------");

        //添加卡权限
        if (list.size() > 0) {
            log.info("卡授权");
            pedestrianHaiKangHandler.addCardAuth(configDTO, list, authDTO);
            try {
                log.info("保存转换卡数据");
                onSavingAuthCards(iAuthAccountCentService, configDTO, pedestrianAuthDTO);
            } catch (Exception e) {
                // 保存转换卡号数据失败
                log.error("海康保存卡数据异常", e);
            }
        }

        if (Objects.isNull(authDTO.getUserOpenIdList()) || authDTO.getUserOpenIdList().size() == 0) {
            log.warn("权限下载失败：参数信息:{}", authDTO);
            return ResultJson.fail("没有找到有效用户");
        }

        pedestrianHaiKangHandler.addAuth(configDTO, authDTO, 5);


        return ResultJson.success();
    }

    @Override
    public ResultJson updateAuth(PedestrianIntegrationConfigDTO configDTO, PedestrianAuthDTO pedestrianAuthDTO) {
        log.info("海康权限更新开始,当前进程:{}",Thread.currentThread().getName());
        log.info(JSONObject.toJSONString(pedestrianAuthDTO));
        // 先删除
        AuthDTO deleteAuthDTO = new AuthDTO();
        deleteAuthDTO.setUserOpenIdList(Collections.singletonList(pedestrianAuthDTO.getUserOpenId()));
        AuthDTO addAuthDTO = new AuthDTO();
        addAuthDTO.setUserId(pedestrianAuthDTO.getSourceId());
        addAuthDTO.setStartTime(pedestrianAuthDTO.getValidStartTime());
        addAuthDTO.setEndTime(pedestrianAuthDTO.getValidEndTime());
        addAuthDTO.setUserOpenIdList(Collections.singletonList(pedestrianAuthDTO.getUserOpenId()));
        List<String> list = Optional.ofNullable(pedestrianAuthDTO.getCardNumberList()).orElse(new LinkedList<>());
        if (pedestrianAuthDTO.getCardNumber() != null) {
            list.add(pedestrianAuthDTO.getCardNumber());
        }
        //添加卡权限
        if (list.size() > 0) {
            log.info("卡授权,{}", pedestrianAuthDTO);
            pedestrianHaiKangHandler.addCardAuth(configDTO, list, addAuthDTO);
            try {
                log.info("保存转换卡数据");
                onSavingAuthCards(iAuthAccountCentService, configDTO, pedestrianAuthDTO);
            } catch (Exception e) {
                // 保存转换卡号数据失败
                log.error("海康保存卡数据异常", e);
            }
        }

        Set<String> deviceIds = new HashSet<>();
        if (!CollectionUtils.isEmpty(pedestrianAuthDTO.getAddedThirdDeviceIdList())) {
            deviceIds.addAll(pedestrianAuthDTO.getAddedThirdDeviceIdList());
        }
        if (!CollectionUtils.isEmpty(pedestrianAuthDTO.getThirdDeviceIdList())) {
            deviceIds.addAll(pedestrianAuthDTO.getThirdDeviceIdList());
        }
        if (!CollectionUtils.isEmpty(deviceIds)) {
            addAuthDTO.setDeviceOpenIdList(new ArrayList<>(deviceIds));
            pedestrianHaiKangHandler.addAuth(configDTO, addAuthDTO, 5);
        }

        if (!CollectionUtils.isEmpty(pedestrianAuthDTO.getDeletedThirdDeviceIdList())) {
            deleteAuthDTO.setDeletedDeviceOpenIdList(pedestrianAuthDTO.getDeletedThirdDeviceIdList());
            pedestrianHaiKangHandler.deleteAuth(configDTO, deleteAuthDTO, 5);
        }


        log.info("海康权限更新结束,当前进程:{}",Thread.currentThread().getName());
        return ResultJson.success();
    }

    @Override
    public ResultJson deleteAuth(PedestrianIntegrationConfigDTO configDTO, PedestrianAuthDTO pedestrianAuthDTO) {
        log.info("海康权限删除:");
        log.info(JSONObject.toJSONString(pedestrianAuthDTO));
        AuthDTO authDTO = new AuthDTO();
        authDTO.setUserOpenIdList(Collections.singletonList(pedestrianAuthDTO.getUserOpenId()));
        List<String> list = Optional.ofNullable(pedestrianAuthDTO.getCardNumberList()).orElse(new LinkedList<>());
        if (pedestrianAuthDTO.getCardNumber() != null) {
            list.add(pedestrianAuthDTO.getCardNumber());
        }
        List<String> deletedCardNumberList = pedestrianAuthDTO.getDeletedCardNumberList();
        //删除卡权限
        if (list.size() > 0) {
            log.info("卡取消绑定,{}", pedestrianAuthDTO);
            pedestrianHaiKangHandler.deleteCardAuth(configDTO, list, authDTO);
        } else if (!CollectionUtils.isEmpty(deletedCardNumberList)) {
            pedestrianHaiKangHandler.deleteCardAuth(configDTO, deletedCardNumberList, authDTO);
        }

        List<DeviceDTO> deviceDTOS;
        Set<String> collect = new HashSet<>();
        if (CollectionUtils.isEmpty(pedestrianAuthDTO.getDeviceIdList()) && CollectionUtils.isEmpty(pedestrianAuthDTO.getThirdDeviceIdList()) && CollectionUtils.isEmpty(pedestrianAuthDTO.getDeletedThirdDeviceIdList())) {
            //查询项目所有门禁设备信息
            deviceDTOS = deviceService.findDevice(pedestrianAuthDTO.getIndustryId(), pedestrianAuthDTO.getProjectId(), CategoryEnum.DOOR.getId(), null);
            collect = deviceDTOS.stream().filter(t -> t.getProductId().equals(ProductEnum.HAIKANG_ISC.getId())).map(DeviceDTO::getThirdDeviceId).collect(Collectors.toSet());
        }
        collect.addAll(pedestrianAuthDTO.getDeletedThirdDeviceIdList());
        authDTO.setDeletedDeviceOpenIdList(new ArrayList<>(collect));
        pedestrianHaiKangHandler.deleteAuth(configDTO, authDTO, 4);
        return ResultJson.success();
    }

    @Override
    public ResultJson openDoor(PedestrianIntegrationConfigDTO pedestrianIntegrationConfigDTO, DeviceDTO deviceDTO, DoorActionEnum doorAction) {
        pedestrianHaiKangHandler.openDoor(pedestrianIntegrationConfigDTO, deviceDTO, doorAction);
        return ResultJson.success();
    }

    private List<OpenDoorRecordDTO> handleRecord(PedestrianIntegrationConfigDTO configDTO, List<PedestrianRecordHaiKangDTO> recordHaiKangDTOList) {
        return recordHaiKangDTOList.stream().map(recordHaiKangDTO -> {
            OpenDoorRecordDTO openDoorRecordDTO = OpenDoorRecordDTO.builder()
                    .projectId(configDTO.getProjectId())
                    .code(recordHaiKangDTO.getEventId())
                    .openDeviceId(recordHaiKangDTO.getDoorIndexCode())
                    .deviceName(recordHaiKangDTO.getDoorName())
                    .sourceType(SourceTypeEnum.USER.type)
                    .arrivalTime(recordHaiKangDTO.getEventTime().format(DateUtils.DATETIME_FORMATTER1))
                    .pictureUrl(StringUtils.isNotEmpty(recordHaiKangDTO.getPicUri()) ? configDTO.getIpAndPort() + recordHaiKangDTO.getPicUri() : null)
                    .state((short) 1)
                    .type(this.handleRecordType(recordHaiKangDTO.getEventType()))
                    .direction(this.handleRecordDirection(recordHaiKangDTO.getInAndOutType()))
                    .approach(AccessApproachEnum.OFF_LINE.getId())
                    .openUserId(recordHaiKangDTO.getPersonId())
                    .userName(recordHaiKangDTO.getPersonName()).build();
            List<PersonInfoHaiKangDTO> personInfoHaiKangDTOS = userHaiKangHandler.detailPerson(
                    "personId",
                    Collections.singletonList(recordHaiKangDTO.getPersonId()),
                    configDTO.getProjectId(),
                    configDTO.getProductId(),
                    configDTO.getIpAndPort(),
                    configDTO.getAk(),
                    configDTO.getSk());
            if (!CollectionUtils.isEmpty(personInfoHaiKangDTOS)) {
                openDoorRecordDTO.setUserIdentityName(personInfoHaiKangDTOS.get(0).getPostType());
            }
            List<RegionHaiKangDTO> regionHaiKangDTOS = regionHaiKangHandler.detailRegion(
                    Collections.singletonList(recordHaiKangDTO.getDoorRegionIndexCode()),
                    configDTO.getProjectId(),
                    configDTO.getProductId(),
                    configDTO.getIpAndPort(),
                    configDTO.getAk(),
                    configDTO.getSk(),
                    configDTO.getTagId());
            if (!CollectionUtils.isEmpty(regionHaiKangDTOS)) {
                openDoorRecordDTO.setArrivalAddress(regionHaiKangDTOS.get(0).getName());
            }
            return openDoorRecordDTO;
        }).collect(Collectors.toList());
    }

    private Short handleRecordType(Integer openType) {
        if (openType == null) {
            return AccessTypeEnum.OTHER.getId();
        }
        switch (openType) {
            case 196893:
                return AccessTypeEnum.FACE.getId();
            case 197127:
                return AccessTypeEnum.FINGERPRINT.getId();
            case 198914:
                return AccessTypeEnum.IC_CARD.getId();
            default:
                return AccessTypeEnum.OTHER.getId();
        }
    }

    private Short handleRecordDirection(Integer direction) {
        if (direction == null) {
            return DirectionEnum.IN.getId();
        }
        switch (direction) {
            case 1:
                return DirectionEnum.IN.getId();
            case 0:
                return DirectionEnum.OUT.getId();
            default:
                return null;
        }
    }

    @Override
    public void pullVisits(PedestrianIntegrationConfigDTO configDTO, Date date) {
        // 拉取数据
        ParamConfigCriteria criteria = new ParamConfigCriteria();
        criteria.code = "VISITOR_RECORD_DEVICE_CONFIG";
        criteria.buzId = configDTO.getProjectId();
        criteria.businessType = BusinessType.PROJECT;
        ParameterConfig sysconfig = iSsyConfigService.findBusinessByCode(criteria);
        if (sysconfig == null || StringUtils.isBlank(sysconfig.getValue())) {
            return;
        }
        List<Integer> deviceIds = Arrays.stream(sysconfig.getValue().split(",")).map(Integer::parseInt).collect(Collectors.toList());
        List<DeviceDTO> devices = deviceService.findDevice(null, configDTO.getProjectId(), null, deviceIds);

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR_OF_DAY, -1);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        List<PedestrianRecordHaiKangDTO> recordHaiKangDTOList = vistorHaikangHandler.pullVisitor(configDTO, devices, calendar.getTime());
        if (CollectionUtils.isEmpty(recordHaiKangDTOList)) {
            return;
        }
        // 转换数据
        List<OpenDoorRecordDTO> openDoorRecordDTOList = this.handleVisitor(configDTO, recordHaiKangDTOList);
        // 存储业务中台
        pedestrianCentService.saveBatch(openDoorRecordDTOList);
    }

    private List<OpenDoorRecordDTO> handleVisitor(PedestrianIntegrationConfigDTO configDTO, List<PedestrianRecordHaiKangDTO> recordHaiKangDTOList) {
        return recordHaiKangDTOList.stream().map(recordHaiKangDTO -> OpenDoorRecordDTO.builder()
                .projectId(configDTO.getProjectId())
                .code(recordHaiKangDTO.getEventId())
                .openDeviceId(recordHaiKangDTO.getDoorIndexCode())
                .deviceName(recordHaiKangDTO.getDoorName())
                .sourceType(SourceTypeEnum.VISITOR_USER.type)
                .arrivalTime(recordHaiKangDTO.getEventTime().format(DateUtils.DATETIME_FORMATTER1))
                .pictureUrl(StringUtils.isNotEmpty(recordHaiKangDTO.getPicUri()) ? configDTO.getIpAndPort() + recordHaiKangDTO.getPicUri() : null)
                .state((short) 1)
                .type(this.handleRecordType(recordHaiKangDTO.getEventType()))
                .direction(this.handleRecordDirection(recordHaiKangDTO.getInAndOutType()))
                .approach(AccessApproachEnum.OFF_LINE.getId())
                .openUserId(recordHaiKangDTO.getPersonId())
                .userName(recordHaiKangDTO.getPersonName()).build()
        ).collect(Collectors.toList());
    }

}
